package com.cain.DontTapTheWhiteTile.render;

import android.opengl.GLES20;
import android.opengl.GLSurfaceView;
import android.util.Log;

import com.cain.DontTapTheWhiteTile.bean.Block;
import com.cain.DontTapTheWhiteTile.tool.FileTool;
import com.cain.DontTapTheWhiteTile.tool.MyCallBack;

import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;

import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;

/**
 * Created by Cain on 2016/6/14.
 * 渲染器
 */
public class GameBoardRender implements GLSurfaceView.Renderer {

    private static final String TAG = "GameBoardRender";

    private String vertexShaderCode;   //顶点着色器代码
    private String fragmentShaderCode;   //片元着色器代码
    private int program;   //着色程序标识
    private int vertexPosition;   //顶点变量在顶点着色器中的位置
    private int vertexColor;   //顶点颜色在顶点着色器中的位置

    public Block[][] blockArray;   //数据源
    private MyCallBack callBack;   //回调

    /**
     * 构造函数，读取着色器代码
     */
    public GameBoardRender(Block[][] blockArray, MyCallBack callBack) {
        if (blockArray == null)
            this.blockArray = new Block[0][0];
        else
            this.blockArray = blockArray;
        this.callBack = callBack;
        vertexShaderCode = FileTool.getStringFromAssets("VertexShader.glsl");
        fragmentShaderCode = FileTool.getStringFromAssets("FragmentShader.glsl");
    }

    /**
     * 加载着色器代码
     * @param type
     * @param source
     * @return
     */
    public static int loadShader(int type, String source) {
        int shader = GLES20.glCreateShader(type);
        GLES20.glShaderSource(shader, source);
        GLES20.glCompileShader(shader);
        return shader;
    }

    /**
     * 当绘制面板创建成功
     * @param gl
     * @param config
     */
    @Override
    public void onSurfaceCreated(GL10 gl, EGLConfig config) {
        int vertexShader = loadShader(GLES20.GL_VERTEX_SHADER, vertexShaderCode);
        int fragmentShader = loadShader(GLES20.GL_FRAGMENT_SHADER, fragmentShaderCode);
        program = GLES20.glCreateProgram();
        GLES20.glAttachShader(program, vertexShader);
        GLES20.glAttachShader(program, fragmentShader);
        GLES20.glLinkProgram(program);
        vertexPosition = GLES20.glGetAttribLocation(program, "vertex_position");
        vertexColor = GLES20.glGetAttribLocation(program, "vertex_color");
        GLES20.glClearColor(82.0f / 255.0f, 214.0f / 255.0f, 104.0f / 255.0f, 1.0f);
    }

    /**
     * 当绘制面板大小改变
     * @param gl
     * @param width
     * @param height
     */
    @Override
    public void onSurfaceChanged(GL10 gl, int width, int height) {
        GLES20.glViewport(0, 0, width, height);
    }

    /**
     * 初始化绘制图形缓冲
     */
    public static FloatBuffer initShapes(float[] pointArray) {
        ByteBuffer pointVBB = ByteBuffer.allocateDirect(pointArray.length * 4);
        pointVBB.order(ByteOrder.nativeOrder());
        FloatBuffer floatBuffer = pointVBB.asFloatBuffer();
        floatBuffer.put(pointArray);
        floatBuffer.position(0);
        return floatBuffer;
    }

    int fps = 0;   //帧率
    long lastPrintFpsTime = 0;   //上一次打印帧率时间
    /**
     * 绘制函数
     * @param gl
     */
    @Override
    public void onDrawFrame(GL10 gl) {
        // --- 打印帧率 ---
        long currentTime = System.currentTimeMillis();
        if (currentTime - lastPrintFpsTime >= 1000) {
            Log.i(TAG, "FPS:" + fps);
            lastPrintFpsTime = currentTime;
            fps = 0;
        }
        ++fps;
        // ----------------

        // --- 清空缓冲 ---
        GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT);
        GLES20.glUseProgram(program);

        // --- 画块 ---
        for (int row = 0; row < blockArray.length; ++row) {
            for (int column = 0; column < blockArray[row].length; ++column) {
                float[] pointArray = blockArray[row][column].getPointArray();
                float[] colorArray = blockArray[row][column].getColorArray();
                FloatBuffer pointBuffer = initShapes(pointArray);
                FloatBuffer colorBuffer = initShapes(colorArray);
                GLES20.glVertexAttribPointer(vertexPosition, 3, GLES20.GL_FLOAT, false, 0, pointBuffer);
                GLES20.glEnableVertexAttribArray(vertexPosition);
                GLES20.glVertexAttribPointer(vertexColor, 4, GLES20.GL_FLOAT, false, 0, colorBuffer);
                GLES20.glEnableVertexAttribArray(vertexColor);
                GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4);
            }
        }

        // --- 画竖线 ---
        for (int row = 0; row < blockArray.length; ++row) {
            for (int column = 0; column < blockArray[row].length - 1; ++column) {
                float[] pointArray = blockArray[row][column].getRightLine();
                float[] colorArray = {
                        0.0f, 0.0f, 0.0f, 1.0f,
                        0.0f, 0.0f, 0.0f, 1.0f
                };
                FloatBuffer pointBuffer = initShapes(pointArray);
                FloatBuffer colorBuffer = initShapes(colorArray);
                GLES20.glVertexAttribPointer(vertexPosition, 3, GLES20.GL_FLOAT, false, 0, pointBuffer);
                GLES20.glEnableVertexAttribArray(vertexPosition);
                GLES20.glVertexAttribPointer(vertexColor, 4, GLES20.GL_FLOAT, false, 0, colorBuffer);
                GLES20.glEnableVertexAttribArray(vertexColor);
                GLES20.glDrawArrays(GLES20.GL_LINES, 0, 2);
            }
        }

        // --- 画横线 ---
        for (int row = 0; row < blockArray.length; ++row) {
            for (int column = 0; column < blockArray[row].length; ++column) {
                float[] pointArray = blockArray[row][column].getBottomLine();
                float[] colorArray = {
                        0.0f, 0.0f, 0.0f, 1.0f,
                        0.0f, 0.0f, 0.0f, 1.0f
                };
                FloatBuffer pointBuffer = initShapes(pointArray);
                FloatBuffer colorBuffer = initShapes(colorArray);
                GLES20.glVertexAttribPointer(vertexPosition, 3, GLES20.GL_FLOAT, false, 0, pointBuffer);
                GLES20.glEnableVertexAttribArray(vertexPosition);
                GLES20.glVertexAttribPointer(vertexColor, 4, GLES20.GL_FLOAT, false, 0, colorBuffer);
                GLES20.glEnableVertexAttribArray(vertexColor);
                GLES20.glDrawArrays(GLES20.GL_LINES, 0, 2);
            }
        }

        callBack.execute(TAG, null);
    }
}
